home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
system
/
ms_sh22b.zip
/
src
/
glob.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-12-01
|
17KB
|
766 lines
/* MS-DOS GLOB (3C) FUNCTION
*
* MS-DOS GLOB FUNCTION - Copyright (c) 1990,1,2 Data Logic Limited.
*
* This code is subject to the following copyright restrictions:
*
* 1. Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice is duplicated in the
* source form.
*
* $Header: /usr/users/istewart/src/shell/sh2.2/RCS/glob.c,v 2.1 1993/06/14 10:59:32 istewart Exp $
*
* $Log: glob.c,v $
* Revision 2.1 1993/06/14 10:59:32 istewart
* More changes for 223 beta
*
* Revision 2.0 1992/04/13 17:39:09 Ian_Stewartson
* MS-Shell 2.0 Baseline release
*
*/
#include <sys/types.h> /* MS-DOS type definitions */
#include <sys/stat.h> /* File status definitions */
#include <stdio.h> /* Standard I/O delarations */
#include <stdlib.h> /* Standard library functions */
#include <string.h> /* String library functions */
#include <limits.h> /* String library functions */
#include <dirent.h> /* Direction I/O functions */
#include <ctype.h> /* Character types function */
#include <unistd.h> /* Other functions */
#ifdef __TURBOC__
# include <alloc.h> /* Malloc functions */
# include <dir.h> /* Dos directory functions */
#else
# include <malloc.h> /* Malloc functions */
#endif
#include <glob.h>
#if defined (MSDOS) || defined (__OS2__) || defined (__TURBOC__)
# if defined (OS2) || defined (__OS2__)
# define INCL_DOSDEVICES
# define INCL_DOSMISC
# include <os2.h> /* OS2 functions declarations */
# if defined (__OS2__)
# define DISABLE_HARD_ERRORS DosError (FERR_DISABLEHARDERR)
# define ENABLE_HARD_ERRORS DosError (FERR_ENABLEHARDERR)
# else
# define DISABLE_HARD_ERRORS DosError (HARDERROR_DISABLE)
# define ENABLE_HARD_ERRORS DosError (HARDERROR_ENABLE)
# endif
# else
# include <bios.h> /* DOS BIOS functions */
# include <dos.h> /* DOS functions */
# define DISABLE_HARD_ERRORS
# define ENABLE_HARD_ERRORS
# endif
#endif
/*
* OS/2 2.x has these missing
*/
#ifndef S_IFMT
# define S_IFMT 0xf000 /* type of file */
#endif
#ifndef S_ISDIR
# define S_ISDIR(m) ((((m) & S_IFMT) == S_IFDIR))
#endif
/*
* Functions
*/
static int _GP_SortCompare _PROTO ((char **, char **));
static int _GP_ExpandField _PROTO ((char *, char *, glob_t *));
static int _GP_ExpandMetaCharacters _PROTO ((char *, glob_t *));
static int _GP_AddArgument _PROTO ((char *, glob_t *));
static bool _GP_MatchPattern _PROTO ((char *, char *));
static bool _GP_access _PROTO ((char *, int));
static bool _GP_stat _PROTO ((char *, struct stat *));
static char *_GP_MetaChars = "?*[\\";
static char *_GP_NullString = "";
#ifdef MSDOS
static int _GP_GetNumberofFloppyDrives (void);
#if defined (OS2) || defined (__OS2__) || defined (__TURBOC__)
static void _dos_setdrive (unsigned int, unsigned int *);
static void _dos_getdrive (unsigned int *);
#endif
static char *_GP_CheckForMultipleDrives _PROTO ((char *));
#endif
/*
* There appears to be no alloca in TurboC
*/
#ifdef __TURBOC__
# define alloca(x) malloc (x)
# define alloca_free(x) free (x)
#else
# define alloca_free(x)
#endif
/*
* Free up space
*/
void globfree (gp)
glob_t *gp;
{
int i = (gp->gl_flags & GLOB_DOOFFS) ? gp->gl_offs : 0;
while (i < gp->gl_pathc)
free (gp->gl_pathv[i++]);
free (gp->gl_pathv);
}
/* Main search function */
int glob (Pattern, flags, ErrorFunction, gp)
char *Pattern;
int flags;
int (*ErrorFunction) _PROTO ((char *, int));
glob_t *gp;
{
int ReturnValue;
char *PatternCopy;
char *cp;
/* If no append mode - initialise */
if (!(flags & GLOB_APPEND))
{
gp->gl_pathc = 0;
gp->gl_pathv = (char **)NULL;
}
gp->gl_flags = flags;
gp->gl_ef = ErrorFunction;
if ((PatternCopy = alloca (strlen (Pattern) + 1)) == (char *)NULL)
return GLOB_NOSPACE;
/* Expand and kill environment */
if (ReturnValue = _GP_ExpandMetaCharacters (strcpy (PatternCopy, Pattern),
gp))
{
alloca_free (PatternCopy);
return ReturnValue;
}
/* Check for no finds. If add value, strip out \ from the string */
if ((gp->gl_pathc == 0) && (flags & GLOB_NOCHECK))
{
cp = strcpy (PatternCopy, Pattern);
while ((cp = strpbrk (cp, "?*[")) != (char *)NULL)
{
if ((cp == PatternCopy) || (*(cp - 1) != '\\'))
cp++;
else
memmove (cp - 1, cp, strlen (cp) + 1);
}
if (ReturnValue = _GP_AddArgument (PatternCopy, gp))
{
alloca_free (PatternCopy);
return ReturnValue;
}
}
/* Terminate string */
if ((gp->gl_pathc != 0) &&
(ReturnValue = _GP_AddArgument ((char *)NULL, gp)))
{
alloca_free (PatternCopy);
return ReturnValue;
}
/* Get the sort length */
ReturnValue = (gp->gl_flags & GLOB_DOOFFS) ? gp->gl_offs : 0;
if ((!(flags & GLOB_NOSORT)) && (gp->gl_pathc > 1))
qsort (&gp->gl_pathv[ReturnValue], gp->gl_pathc, sizeof (char *),
_GP_SortCompare);
alloca_free (PatternCopy);
return 0;
}
/* Compare function for sort */
static int _GP_SortCompare (a1, a2)
char **a1, **a2;
{
return strcmp (*a1, *a2);
}
/* Expand a field if it has metacharacters in it */
static int _GP_ExpandField (CurrentDirectoryPattern, AppendString, gp)
char *CurrentDirectoryPattern; /* Prefix field */
char *AppendString; /* Postfix field */
glob_t *gp;
{
int i;
int ReturnValue = 0; /* Return Value */
char *FullFileName; /* Search file name */
char *FileNameStart;
char *MatchString; /* Match string */
DIR *DirHandler;
struct dirent *CurrentDirectoryEntry;
#ifdef MSDOS
unsigned int CurrentDrive; /* Current drive */
unsigned int MaxDrives; /* Max drive */
unsigned int SelectedDrive; /* Selected drive */
unsigned int x_drive, y_drive; /* Dummies */
char *DriveCharacter; /* Multi-drive flag */
char SDriveString[2];
/* Convert file name to lower case */
#if defined (OS2) || defined (__OS2__)
if (!IsHPFSFileSystem (CurrentDirectoryPattern))
strlwr (CurrentDirectoryPattern);
#else
strlwr (CurrentDirectoryPattern);
#endif
/* Search all drives ? */
if ((DriveCharacter = _GP_CheckForMultipleDrives (CurrentDirectoryPattern))
!= (char *)NULL)
{
_dos_getdrive (&CurrentDrive); /* Get number of drives */
_dos_setdrive (CurrentDrive, &MaxDrives);
SDriveString[1] = 0;
for (SelectedDrive = 1; SelectedDrive <= MaxDrives; ++SelectedDrive)
{
_dos_setdrive (SelectedDrive, &x_drive);
_dos_getdrive (&y_drive);
_dos_setdrive (CurrentDrive, &x_drive);
/* Check to see if the second diskette drive is really there */
if ((_GP_GetNumberofFloppyDrives () < 2) && (SelectedDrive == 2))
continue;
/* If the drive exists and is in our list - process it */
*DriveCharacter = 0;
*SDriveString = (char)(SelectedDrive + 'a' - 1);
strlwr (CurrentDirectoryPattern);
if ((y_drive == SelectedDrive) &&
_GP_MatchPattern (SDriveString, CurrentDirectoryPattern))
{
if ((FullFileName = alloca (strlen (DriveCharacter) + 3))
== (char *)NULL)
return GLOB_NOSPACE;
*DriveCharacter = ':';
*FullFileName = *SDriveString;
strcpy (FullFileName + 1, DriveCharacter);
i = _GP_ExpandField (FullFileName, AppendString, gp);
alloca_free (FullFileName);
if (i)
return i;
}
*DriveCharacter = ':';
}
return 0;
}
#endif
/* Get the path length */
MatchString = strrchr (CurrentDirectoryPattern, '/');
#ifdef MSDOS
if ((MatchString == (char *)NULL) &&
(*(CurrentDirectoryPattern + 1) == ':'))
MatchString = CurrentDirectoryPattern + 1;
#endif
/* Set up file name for search */
if ((MatchString == (char *)NULL) || (*MatchString == ':'))
{
if ((FullFileName = alloca (NAME_MAX + 7 +
strlen (AppendString))) == (char *)NULL)
return GLOB_NOSPACE;
if (MatchString != (char *)NULL)
*(strcpy (FullFileName, "x:.")) = *CurrentDirectoryPattern;
else
strcpy (FullFileName, ".");
FileNameStart = FullFileName +
(int)((MatchString != (char *)NULL) ? 2 : 0);
}
/* Case of /<directory>/... */
else if ((FullFileName = alloca (NAME_MAX + 4 + strlen (AppendString)